package com.fan.gofast.config;

import cn.hutool.core.text.UnicodeUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHeaders;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.*;
import org.springframework.http.converter.*;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Configuration
@Slf4j
public class RestTemplateConfig {

    private static final int BUFFER_SIZE = 4096;

    private List<HttpMessageConverter<?>> getMessageConverterList() {
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        messageConverters.add(new ByteArrayHttpMessageConverter());
        messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        messageConverters.add(new ResourceHttpMessageConverter());
        messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        messageConverters.add(new FormHttpMessageConverter());
        messageConverters.add(new MappingJackson2HttpMessageConverter());
        return messageConverters;
    }

    @Bean
    public RestTemplate restTemplate(){
        List<HttpMessageConverter<?>> messageConverters = getMessageConverterList();
        RestTemplate restTemplate = new RestTemplateBuilder().additionalMessageConverters(messageConverters).build();
        restTemplate.setRequestFactory(createFactory());
        restTemplate.setInterceptors(Lists.newArrayList(restLogInterceptor()));
        return restTemplate;
    }

    private ClientHttpRequestInterceptor restLogInterceptor() {
        return (HttpRequest httpRequest, byte[] body, ClientHttpRequestExecution execution) -> {
            log.info("------------------------rest request----------------------------");
            log.info("request url:" + httpRequest.getURI());
            log.info("request header:" + httpRequest.getHeaders().toString());
            log.info("request method:" + httpRequest.getMethodValue());
            log.info("request body:" + new String(body,StandardCharsets.UTF_8));
            long startTime = System.currentTimeMillis();
            ClientHttpResponse response = execution.execute(httpRequest, body);
            byte[] bytes = new byte[0];
            if (response.getStatusCode() == HttpStatus.OK
                    || response.getStatusCode() == HttpStatus.CREATED ) {
                bytes = inputStreamToByte(response.getBody());
            }

            log.info("-----------------------rest response----------------------------");
            log.info("response code:" + response.getStatusCode());
            log.info("response code msg:" + response.getStatusText());
            log.info("response headers:" + response.getHeaders().toString());
            if (!response.getHeaders().get(HttpHeaders.CONTENT_TYPE).contains(MediaType.APPLICATION_OCTET_STREAM_VALUE)){
                log.info("response body:" + UnicodeUtil.toString(new String(bytes, StandardCharsets.UTF_8)));
            }
            // 执行耗时
            log.info("rest-time-cost : {} ms", System.currentTimeMillis() - startTime);
            return new ClientHttpResponseWrapper(response, bytes);
        };
    }

    private byte[] inputStreamToByte(InputStream inputStream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] bytes = new byte[BUFFER_SIZE];
        int length;
        while ((length = inputStream.read(bytes, 0, BUFFER_SIZE)) != -1) {
            outputStream.write(bytes, 0, length);
        }
        return outputStream.toByteArray();
    }

    public HttpClient httpClient(){
        // 连接池
        PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
        // 最大连接数
        poolingConnectionManager.setMaxTotal(1000);
        // 每个主机的并发
        poolingConnectionManager.setDefaultMaxPerRoute(100);
        // 空闲连接过期时间
        poolingConnectionManager.setValidateAfterInactivity(10_000);
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setConnectionManager(poolingConnectionManager);
        return httpClientBuilder.build();
    }

    @Bean
    public ClientHttpRequestFactory createFactory() {
        HttpClient httpClient = httpClient();
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setHttpClient(httpClient);
        //连接请求超时时间
        httpRequestFactory.setConnectionRequestTimeout(30*1000);
        //客户端和服务器建立连接的超时时间
        httpRequestFactory.setConnectTimeout(15*1000);
        //读取数据的超时时间
        httpRequestFactory.setReadTimeout(30*1000);
        return httpRequestFactory;
    }














}
